/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.inspur.edp.web.common.logger;

import com.inspur.edp.web.common.utility.StringUtility;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Arrays;

/**
 * web 统一的日志输出类 使用枚举的目的是为了保证绝对单例
 *
 * @author noah
 */
public enum WebLogger {
    /**
     * 使用枚举的单例特性
     */
    Instance;

    /**
     * 内部定义枚举类 标识日志级别
     */
    private enum WebLoggerLevel {
        Debug {
            /**
             * 抽象类 使用各个枚举参数进行日志写入
             *
             * @param loggerInstance
             */
            @Override
            void write(String message, Logger loggerInstance) {
                if (loggerInstance.isDebugEnabled()) {
                    loggerInstance.debug(message);
                }
            }
        }, Info {
            /**
             * 抽象类 使用各个枚举参数进行日志写入
             *
             * @param message
             * @param loggerInstance
             */
            @Override
            void write(String message, Logger loggerInstance) {
                if (loggerInstance.isInfoEnabled()) {
                    loggerInstance.info(message);
                }
            }
        }, Warn {
            /**
             * 抽象类 使用各个枚举参数进行日志写入
             *
             * @param message
             * @param loggerInstance
             */
            @Override
            void write(String message, Logger loggerInstance) {
                if (loggerInstance.isWarnEnabled()) {
                    loggerInstance.warn(message);
                }
            }
        }, Error {
            /**
             * 抽象类 使用各个枚举参数进行日志写入
             *
             * @param message
             * @param loggerInstance
             */
            @Override
            void write(String message, Logger loggerInstance) {
                if (loggerInstance.isErrorEnabled()) {
                    loggerInstance.error(message);
                }
            }
        };

        /**
         * 抽象类 使用各个枚举参数进行日志写入
         *
         * @param loggerInstance
         */
        abstract void write(String message, Logger loggerInstance);
    }

    /**
     * 根据指定class获取对应的logger实例
     * 内置包含对logger实例的缓存动作，
     * 尽量使用默认logger，避免重复创建logger实例带来的内存开销
     *
     * @param name
     * @return
     */
    private Logger getLoggerInstance(String name) {
        // 内置包含对logger实例的缓存操作
        if (StringUtility.isNullOrEmpty(name)) {
            return LoggerFactory.getLogger(this.defaultLoggerName);
        }
        return LoggerFactory.getLogger(name);
    }

    private final String defaultLoggerName = WebLogger.class.getName();


    /**
     * 执行debug级别日志消息写入
     *
     * @param message    待写入的消息内容
     * @param loggerName 自定义的日志名称
     */
    public void debug(String message, String... loggerName) {
        this.write(message, WebLoggerLevel.Debug, loggerName);
    }

    /**
     * 执行info级别的日志写入
     *
     * @param message    待写入的消息内容
     * @param loggerName 自定义的日志写入名称
     */
    public void info(String message, String... loggerName) {
        this.write(message, WebLoggerLevel.Info, loggerName);
    }

    /**
     * @param message
     * @param loggerName
     */
    public void error(String message, String... loggerName) {
        this.write(message, WebLoggerLevel.Error, loggerName);
    }

    /**
     * 输出异常信息
     *
     * @param ex
     * @param loggerName
     */
    public void error(Exception ex, String... loggerName) {
        this.error(ex.getMessage() + Arrays.toString(ex.getStackTrace()), loggerName);
    }

    /**
     * 异常信息日志记录
     *
     * @param ex
     * @param customErrorMessage
     * @param loggerName
     */
    public void errorWithCustomMessage(Exception ex, String customErrorMessage, String... loggerName) {
        if (StringUtility.isNullOrEmpty(customErrorMessage)) {
            this.error(ex, loggerName);
        } else {
            this.error(customErrorMessage + ex.getMessage() + Arrays.toString(ex.getStackTrace()), loggerName);
        }
    }

    public void warn(String message, String... loggerName) {
        this.write(message, WebLoggerLevel.Warn, loggerName);
    }

    /**
     * 执行日志消息写入
     *
     * @param message
     * @param loggerLevel
     * @param loggerName
     */
    private void write(String message, WebLoggerLevel loggerLevel, String... loggerName) {
        if (StringUtility.isNullOrEmpty(message)) {
            return;
        }
        Logger logger = getLogger(loggerName);

        if (logger != null) {
            loggerLevel.write(message, logger);
        }
    }

    /**
     * 创建对应的logger实例
     * 提取函数，避免方法过长且复杂
     *
     * @param loggerName
     * @return
     */
    private Logger getLogger(String[] loggerName) {
        Logger logger;
        if (loggerName != null && loggerName.length > 0) {
            logger = getLoggerInstance(loggerName[0]);
        } else {
            logger = getLoggerInstance(null);
        }
        return logger;
    }

}
